package com.wsoft.bpm.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.wsoft.bpm.bean.ApprovalChainNode;
import com.wsoft.bpm.bean.CountersignElement;
import com.wsoft.bpm.bean.DynamicApprovalChain;
import com.wsoft.bpm.component.command.TaskSaveInstCmd;
import com.wsoft.bpm.service.RunProcessService;
import com.wsoft.core.exception.ApiException;
import com.wsoft.core.exception.Asserts;
import org.activiti.engine.ManagementService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.persistence.entity.TaskEntityImpl;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.wsoft.bpm.constants.BpmConstant.DYNAMIC_CHAIN_NODE;
import static com.wsoft.bpm.constants.BpmConstant.DYNAMIC_ORIGIN_TASK_ID;
import static com.wsoft.bpm.constants.BpmConstant.Hr.VARIABLE_KEY_DYNAMIC_APPROVAL_CHAIN_KEY;

/**
 * 绩效工作流服务类
 *
 * @author zhonglj
 * @date 2025/2/14 14:20
 **/
@Service
public class ChainWorkFlowService {
    @Resource
    private RunProcessService runProcessService;
    @Resource
    private TaskService taskService;
    @Resource
    private ManagementService managementService;
    @Resource
    private RuntimeService runtimeService;

    /**
     * 流程同意
     *
     * @param taskId
     * @param comment
     * @return void
     * @author zhonglj
     * @date 2025/2/14 14:39
     **/
    @Transactional(rollbackFor = Exception.class)
    public void agree(String taskId, String comment) {
        Task currentTask = runProcessService.getAuthTask(taskId, true);
        agree(currentTask, comment);
    }

    /**
     * 流程驳回
     *
     * @param taskId
     * @param comment
     * @return void
     * @author zhonglj
     * @date 2025/2/18 9:47
     **/
    public void rollback(String taskId, String comment) {
        runProcessService.rollback(taskId, comment);
    }

    /**
     * 重新设置动态审批链
     *
     * @param businessKey 业务编码
     * @param variableKey 动态审批链变量名
     * @param newNodes    新的动态节点列表
     * @return boolean
     * @author zhonglj
     * @date 2025/2/18 11:15
     **/
    public boolean resetDynamicApprovalChain(String businessKey, String variableKey, ArrayList<ApprovalChainNode> newNodes) {
        if (CollUtil.isEmpty(newNodes)) {
            return false;
        }

        List<ProcessInstance> list = runtimeService.createProcessInstanceQuery()
                .processInstanceBusinessKey(businessKey)
                .active()
                .orderByProcessInstanceId()
                .desc()
                .list();
        if (CollUtil.isEmpty(list)) {
            return false;
        }
        ProcessInstance processInstance = list.get(0);

        DynamicApprovalChain chain = runtimeService.getVariable(processInstance.getId(), variableKey, DynamicApprovalChain.class);
        boolean resetChain = chain.resetChain(newNodes);
        if (!resetChain) {
            return false;
        }
        // 更新流程变量
        runtimeService.setVariable(processInstance.getId(), variableKey, chain);
        return true;
    }

    /**
     * 创建动态审批节点
     *
     * @param originTaskId      来源节点id
     * @param sourceTaskId      来源节点id
     * @param dynamicAssignList 动态审批人列表
     * @param taskName          动态审批节点名称
     * @return void
     * @author zhonglj
     * @date 2025/2/18 13:10
     **/
    public void addDynamicChainNode(String originTaskId, String sourceTaskId, List<String> dynamicAssignList, String taskName) {
        Task originTask = taskService.createTaskQuery().taskId(originTaskId).singleResult();
        for (String assign : dynamicAssignList) {
            // 创建任务
            TaskEntityImpl dynamicTask = (TaskEntityImpl) taskService.newTask();
            dynamicTask.setProcessInstanceId(originTask.getProcessInstanceId());
            dynamicTask.setProcessDefinitionId(originTask.getProcessDefinitionId());
//            dynamicTask.setExecutionId(originTask.getExecutionId());
            dynamicTask.setTaskDefinitionKey(originTask.getTaskDefinitionKey());
            dynamicTask.setName(taskName);
            dynamicTask.setCategory(DYNAMIC_CHAIN_NODE);
            dynamicTask.setAssignee(assign);
            dynamicTask.setParentTaskId(sourceTaskId);
            managementService.executeCommand(new TaskSaveInstCmd(dynamicTask));
        }

        // 临时变量
        taskService.setVariableLocal(sourceTaskId, DYNAMIC_ORIGIN_TASK_ID, originTaskId);
    }

    @Transactional(rollbackFor = Exception.class)
    public void refuse(String taskId, String comment) {
        Task currentTask = runProcessService.getAuthTask(taskId, true);
        refuse(currentTask, comment);
    }

    @Transactional(rollbackFor = Exception.class)
    public void refuse(Task task, String comment) {
        String taskId = task.getId();
        String originTaskId = taskService.getVariableLocal(task.getParentTaskId(), DYNAMIC_ORIGIN_TASK_ID, String.class);
        String chainKey = taskService.getVariableLocal(originTaskId, VARIABLE_KEY_DYNAMIC_APPROVAL_CHAIN_KEY, String.class);
        DynamicApprovalChain approvalChain = runtimeService.getVariable(task.getProcessInstanceId(), chainKey, DynamicApprovalChain.class);
        if (approvalChain == null) {
            return;
        }
        CountersignElement countersign = approvalChain.getCurrentNode().getCountersignElement();
        if (countersign != null) {
            String variableKey = taskService.getVariableLocal(originTaskId, VARIABLE_KEY_DYNAMIC_APPROVAL_CHAIN_KEY, String.class);
            // 累加拒绝人数
            countersign.increaseRefuse();
            // 手动更新动态审批链路
            taskService.setVariable(originTaskId, variableKey, approvalChain);
            // 结束当前任务
            if (StrUtil.isNotBlank(comment)) {
                taskService.addComment(taskId, task.getProcessInstanceId(), comment);
            }
            taskService.complete(taskId);

            String sourceTaskId = task.getParentTaskId();
            if (StrUtil.isBlank(sourceTaskId)) {
                Asserts.fail("获取来源节点失败!");
            }
            if (isAllCompleteUnderSource(sourceTaskId)) {
                // 获取审批节点会签结果
                int completeResult = countersign.completeResult();
                if (completeResult == CountersignElement.COMPLETE_RESULT_AGREE) {
                    if (approvalChain.hasNextNode()) {
                        //获取下一个节点配置
                        ApprovalChainNode nextNode = approvalChain.nextNode();
                        // 手动更新动态审批链路
                        taskService.setVariable(originTaskId, variableKey, approvalChain);
                        // 生成动态节点
                        addDynamicChainNode(originTaskId, originTaskId, nextNode.getAssignList(), nextNode.getApprovalName());
                    }

                } else if (completeResult == CountersignElement.COMPLETE_RESULT_REFUSE) {
                    // 走审批节点拒绝流程
                    normalRefuse(sourceTaskId, null, task.getProcessInstanceId());
                } else if (completeResult == CountersignElement.COMPLETE_RESULT_RUNNING) {
                    // 审批中
                }
            }

        } else {
            // 结束当前任务
            taskService.addComment(taskId, task.getProcessInstanceId(), comment);
            taskService.complete(taskId);
            // 非会签-流程节点拒绝
            normalRefuse(originTaskId, null, task.getProcessInstanceId());
        }

    }

    private void normalRefuse(String taskId, String comment, String processInstanceId) {
        // 结束当前任务下的所有子任务
        List<Task> subTasks = getSubTasks(taskId);
        subTasks.stream().forEach(subTask -> taskService.complete(subTask.getId()));

        if (StrUtil.isNotBlank(comment)) {
            taskService.addComment(taskId, processInstanceId, comment);
        }

        // 动态审批链节点退回
        String chainKey = taskService.getVariableLocal(taskId, VARIABLE_KEY_DYNAMIC_APPROVAL_CHAIN_KEY, String.class);
        DynamicApprovalChain approvalChain = runtimeService.getVariable(processInstanceId, chainKey, DynamicApprovalChain.class);
        if (approvalChain != null) {
            // 往前退一步
            ApprovalChainNode preNode = approvalChain.preNode();
            if (preNode != null) {
                // 手动更新动态审批链路
                taskService.setVariable(taskId, chainKey, approvalChain);
                // 生成上一个节点的动态审批任务
                addDynamicChainNode(taskId, taskId, preNode.getAssignList(), preNode.getApprovalName());
                return;
            }
        }

        // 工作流设计节点退回
        try {
            runProcessService.backOne(taskId, null, false);
        } catch (ApiException e) {
            if (StrUtil.equals(e.getMessage(), "[bpm.process.error.backOne.empty]")) {
                // 流程实例结束，退回制单人
                runProcessService.rollback(taskId, null, false);
            } else {
                throw e;
            }
        }
    }

    /**
     * 流程同意
     *
     * @param task
     * @param comment
     * @return void
     * @author zhonglj
     * @date 2025/2/14 14:39
     **/
    @Transactional(rollbackFor = Exception.class)
    public void agree(Task task, String comment) {
        String taskId = task.getId();
        String originTaskId = taskService.getVariableLocal(task.getParentTaskId(), DYNAMIC_ORIGIN_TASK_ID, String.class);
        String chainKey = taskService.getVariableLocal(originTaskId, VARIABLE_KEY_DYNAMIC_APPROVAL_CHAIN_KEY, String.class);
        DynamicApprovalChain approvalChain = runtimeService.getVariable(task.getProcessInstanceId(), chainKey, DynamicApprovalChain.class);
        if (approvalChain == null) {
            return;
        }
        CountersignElement countersign = approvalChain.getCurrentNode().getCountersignElement();
        if (countersign != null) {
            String variableKey = taskService.getVariableLocal(originTaskId, VARIABLE_KEY_DYNAMIC_APPROVAL_CHAIN_KEY, String.class);
            // 累加同意人数
            countersign.increaseAgree();
            // 手动更新动态审批链路
            taskService.setVariable(originTaskId, variableKey, approvalChain);
            // 结束当前任务
            if (StrUtil.isNotBlank(comment)) {
                taskService.addComment(taskId, task.getProcessInstanceId(), comment);
            }
            taskService.complete(taskId);

            String sourceTaskId = task.getParentTaskId();
            if (isAllCompleteUnderSource(sourceTaskId)) {
                // 子任务全部完成,判断会签结果
                int completeResult = countersign.completeResult();
                if (completeResult == CountersignElement.COMPLETE_RESULT_AGREE) {
                    // 来源节点完成
                    normalAgree(sourceTaskId, task.getProcessInstanceId(), null);

                } else if (completeResult == CountersignElement.COMPLETE_RESULT_REFUSE) {
                    // 走审批节点拒绝流程
                    normalRefuse(sourceTaskId, null, task.getProcessInstanceId());

                } else if (completeResult == CountersignElement.COMPLETE_RESULT_RUNNING) {
                    // 运行中
                }

            }

        } else {
            // 非会签同意
            taskService.addComment(taskId, task.getProcessInstanceId(), comment);
            taskService.complete(taskId);

            String sourceTaskId = task.getParentTaskId();
            if (isAllCompleteUnderSource(sourceTaskId)) {
                // 子任务全部完成,来源节点完成
                normalAgree(sourceTaskId, task.getProcessInstanceId(), null);
            }

        }

    }

    /**
     * 流程定义节点的审核同意
     *
     * @param taskId            来源节点id
     * @param processInstanceId 流程实例id
     * @param comment
     * @return void
     * @author zhonglj
     * @date 2025/2/14 14:40
     **/
    private void normalAgree(String taskId, String processInstanceId, String comment) {
        if (StrUtil.isNotBlank(comment)) {
            taskService.addComment(taskId, processInstanceId, comment);
        }
        // 获取下一个动态审批节点
        ApprovalChainNode nextDynamicNode = getNextDynamicNode(taskId);
        if (nextDynamicNode != null) {
            // 创建动态节点动态节点
            addDynamicChainNode(taskId, taskId, nextDynamicNode.getAssignList(), nextDynamicNode.getApprovalName());
        } else {
            taskService.complete(taskId);
        }
    }

    /**
     * 获取下一个动态节点
     *
     * @param originTaskId
     * @return com.wsoft.bpm.bean.ParallelApprovalNode
     * @author zhonglj
     * @date 2025/2/14 16:11
     **/
    private ApprovalChainNode getNextDynamicNode(String originTaskId) {
        String variableKey = taskService.getVariableLocal(originTaskId, VARIABLE_KEY_DYNAMIC_APPROVAL_CHAIN_KEY, String.class);
        // 获取动态审批链
        DynamicApprovalChain chain = taskService.getVariable(originTaskId, variableKey, DynamicApprovalChain.class);
        if (chain == null) {
            return null;
        }
        ApprovalChainNode nextNode = chain.nextNode();
        // 手动更新动态审批链路
        taskService.setVariable(originTaskId, variableKey, chain);
        return nextNode;
    }

    /**
     * 来源任务下所有并行子任务都完成
     *
     * @param sourceTaskId
     * @return boolean
     * @author zhonglj
     * @date 2024/12/7 13:50
     **/
    private boolean isAllCompleteUnderSource(String sourceTaskId) {
        return CollUtil.isEmpty(getSubTasks(sourceTaskId));
    }

    private List<Task> getSubTasks(String sourceTaskId) {
        return taskService.createTaskQuery()
                .taskParentTaskId(sourceTaskId)
                .active()
                .list()
                .stream()
                .collect(Collectors.toList());
    }


}
